package com.fw.service.merchantprofile.impl;

import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.log4j.Logger;
import org.apache.velocity.VelocityContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;

import com.fw.service.applicationlog.ApplicationLogService;
import com.fw.service.applicationlog.bean.ApplicationLogBean;
import com.fw.service.auditlog.AuditLogService;
import com.fw.service.auditlog.bean.AuditLogBean;
import com.fw.service.bean.EntryBean;
import com.fw.service.bean.ErrorBean;
import com.fw.service.bean.SearchCriteriaBean;
import com.fw.service.bean.SearchResultBean;
import com.fw.service.formvalidator.FormValidatorService;
import com.fw.service.masterdata.MasterDataService;
import com.fw.service.merchantprofile.MerchantProfileService;
import com.fw.service.merchantprofile.bean.MerchantProfileBean;
import com.fw.service.merchantprofile.bean.SearchMerchantProfileBean;
import com.fw.service.merchantprofile.template.MerchantProfileCSVTemplate;
import com.fw.service.persistence.MerchantProfilePersistenceService;
import com.fw.service.persistence.dto.Error;
import com.fw.service.persistence.dto.MerchantProfile;
import com.fw.service.property.PropertyService;
import com.fw.util.DataUtils;
import com.fw.util.DateUtils;
import com.fw.util.PageRequestUtils;
import com.fw.util.StringUtils;
import com.fw.util.VelocityUtil;

public class MerchantProfileServiceImpl implements MerchantProfileService {

    private static Logger log = Logger.getLogger(MerchantProfileServiceImpl.class.getName());

    @Autowired
    private PropertyService propertyService;

    @Autowired
    private MasterDataService masterDataService;

    @Autowired
    private ApplicationLogService applicationLogService;

    @Autowired
    private AuditLogService auditLogService;

    @Autowired
    private FormValidatorService formValidatorService;

    @Autowired
    private MerchantProfilePersistenceService merchantProfilePersistenceService;

    @Override
    public List<EntryBean<String, Serializable>> createMerchantProfile(MerchantProfileBean merchantProfileBean) {
	String clazz = MerchantProfileService.class.getName();
	String method = "createMerchantProfile";
	List<EntryBean<String, Serializable>> entryBeans = null;
	try {
	    ApplicationLogBean applicationLogBean = new ApplicationLogBean();
	    applicationLogBean.setType(ApplicationLogBean.TYPE_INFO);
	    applicationLogBean.setClazz(clazz);
	    applicationLogBean.setMethod(method);
	    applicationLogBean.setMessage(method);
	    applicationLogService.createApplicationLog(applicationLogBean);

	    if (merchantProfileBean != null) {
		entryBeans = new ArrayList<EntryBean<String, Serializable>>();
		// validate
		List<Error> errors = formValidatorService.validate(clazz, method, merchantProfileBean);
		List<ErrorBean> errorBeans = new ArrayList<ErrorBean>();
		if (errors != null && !errors.isEmpty()) {
		    for (Error error : errors) {
			ErrorBean errorBean = new ErrorBean();
			BeanUtils.copyProperties(error, errorBean);
			errorBeans.add(errorBean);
		    }
		}
		// validate unique
		if (!this.checkUniqueMerchantId(merchantProfileBean.getMerchantId())) {
		    ErrorBean errorBean = new ErrorBean();
		    errorBean
			    .setErrorCode("errors.com.fw.service.merchantprofile.MerchantProfileService.createMerchantProfile.merchantIdExist");
		    errorBeans.add(errorBean);
		}
		if (errorBeans != null && !errorBeans.isEmpty()) {
		    entryBeans.add(new EntryBean<String, Serializable>(List.class.getName() + "." + ErrorBean.class.getName(),
			    (Serializable) errorBeans));
		} else {
		    Date currentDate = DateUtils.getCurrentDate();
		    String currentDateStr = StringUtils.formatDate(currentDate, StringUtils.PATTERN_DATETIME_PERSISTENCE);
		    // save
		    MerchantProfile merchantProfile = new MerchantProfile();
		    BeanUtils.copyProperties(merchantProfileBean, merchantProfile);
		    // merchantProfile.setMerchantStatus(MerchantProfile.STATUS_ACTIVE);
		    merchantProfile.setCreateBy(merchantProfileBean.getLoginUsername());
		    merchantProfile.setCreateDate(currentDateStr);
		    merchantProfile.setLastUpdateBy(merchantProfileBean.getLoginUsername());
		    merchantProfile.setLastUpdateDate(currentDateStr);
		    merchantProfile = merchantProfilePersistenceService.save(merchantProfile);

		    MerchantProfileBean resultBoUserBean = new MerchantProfileBean();
		    BeanUtils.copyProperties(merchantProfile, resultBoUserBean);
		    resultBoUserBean.setId(merchantProfile.getId());
		    // audit log
		    String logActionType = propertyService.getProperty("auditlog." + clazz + "." + method);
		    if (logActionType != null) {
			AuditLogBean auditLogBean = new AuditLogBean();
			auditLogBean.setLogActionType(logActionType);
			auditLogBean.setDescription(merchantProfileBean.getMerchantId() + " created by "
				+ merchantProfileBean.getLoginUsername());
			auditLogBean.setGroupId(merchantProfileBean.getLoginRoleId());
			auditLogBean.setUserId(merchantProfileBean.getLoginUserId());
			auditLogBean.setDateTime(currentDateStr);
			auditLogBean.setUserIp(merchantProfileBean.getUserIp());
			auditLogService.createAuditLog(auditLogBean);
		    }
		    entryBeans.add(new EntryBean<String, Serializable>(resultBoUserBean.getClass().getName(), resultBoUserBean));
		}
	    }
	} catch (Exception e) {
	    log.error(e, e);
	    ApplicationLogBean applicationLogBean = new ApplicationLogBean();
	    applicationLogBean.setType(ApplicationLogBean.TYPE_ERROR);
	    applicationLogBean.setClazz(clazz);
	    applicationLogBean.setMethod(method);
	    applicationLogBean.setMessage(e.getMessage());
	    applicationLogService.createApplicationLog(applicationLogBean);
	}
	return entryBeans;
    }

    @Override
    public MerchantProfileBean getMerchantProfile(Long id) {
	MerchantProfileBean merchantProfileBean = null;
	try {
	    MerchantProfile merchantProfile = merchantProfilePersistenceService.findOne(id);
	    if (merchantProfile != null) {
		merchantProfileBean = new MerchantProfileBean();
		BeanUtils.copyProperties(merchantProfile, merchantProfileBean);
		merchantProfileBean.setId(merchantProfile.getId());
	    }
	} catch (Exception e) {
	    log.error(e, e);
	}
	return merchantProfileBean;
    }

    @Override
    public List<EntryBean<String, Serializable>> updateMerchantProfile(MerchantProfileBean merchantProfileBean) {
	String clazz = MerchantProfileService.class.getName();
	String method = "updateMerchantProfile";
	List<EntryBean<String, Serializable>> entryBeans = null;
	MerchantProfile merchantProfile = null;
	try {

	    if (merchantProfileBean != null) {
		merchantProfile = merchantProfilePersistenceService.findOne(merchantProfileBean.getId());
		if (merchantProfile != null && isDataChange(merchantProfile, merchantProfileBean)) {

		    ApplicationLogBean applicationLogBean = new ApplicationLogBean();
		    applicationLogBean.setType(ApplicationLogBean.TYPE_INFO);
		    applicationLogBean.setClazz(clazz);
		    applicationLogBean.setMethod(method);
		    applicationLogBean.setMessage(method);
		    applicationLogService.createApplicationLog(applicationLogBean);

		    entryBeans = new ArrayList<EntryBean<String, Serializable>>();
		    // validate
		    List<Error> errors = formValidatorService.validate(clazz, method, merchantProfileBean);
		    List<ErrorBean> errorBeans = new ArrayList<ErrorBean>();
		    if (errors != null && !errors.isEmpty()) {
			for (Error error : errors) {
			    ErrorBean errorBean = new ErrorBean();
			    BeanUtils.copyProperties(error, errorBean);
			    errorBeans.add(errorBean);
			}
		    }
		    if (errorBeans != null && !errorBeans.isEmpty()) {
			entryBeans.add(new EntryBean<String, Serializable>(List.class.getName() + "." + ErrorBean.class.getName(),
				(Serializable) errorBeans));
		    } else {
			// if (merchantProfile != null && !MerchantProfile.STATUS_INACTIVE.equals(merchantProfile.getStatus())) {
			Date currentDate = DateUtils.getCurrentDate();
			String currentDateStr = StringUtils.formatDate(currentDate, StringUtils.PATTERN_DATETIME_PERSISTENCE);
			// copy from bean
			BeanUtils
				.copyProperties(merchantProfileBean, merchantProfile, "id", "merchantId", "merchantServiceType", "mccCode");
			merchantProfile.setLastUpdateBy(merchantProfileBean.getLoginUsername());
			merchantProfile.setLastUpdateDate(currentDateStr);
			merchantProfile = merchantProfilePersistenceService.save(merchantProfile);
			MerchantProfileBean resultBoUserBean = new MerchantProfileBean();
			BeanUtils.copyProperties(merchantProfile, resultBoUserBean);
			resultBoUserBean.setId(merchantProfile.getId());

			// audit log
			String logActionType = propertyService.getProperty("auditlog." + clazz + "." + method);
			if (logActionType != null) {
			    AuditLogBean auditLogBean = new AuditLogBean();
			    auditLogBean.setLogActionType(logActionType);
			    auditLogBean.setDescription(merchantProfileBean.getMerchantId() + " : "
				    + merchantProfileBean.getMerchantNameTh() + " updated by " + merchantProfileBean.getLoginUsername());
			    auditLogBean.setGroupId(merchantProfileBean.getLoginRoleId());
			    auditLogBean.setUserId(merchantProfileBean.getLoginUserId());
			    auditLogBean.setDateTime(currentDateStr);
			    auditLogBean.setUserIp(merchantProfileBean.getUserIp());
			    auditLogService.createAuditLog(auditLogBean);
			}
			entryBeans.add(new EntryBean<String, Serializable>(resultBoUserBean.getClass().getName(), resultBoUserBean));
			// }
		    }
		} else {
		    entryBeans = new ArrayList<EntryBean<String, Serializable>>();
		    entryBeans.add(new EntryBean<String, Serializable>(merchantProfileBean.getClass().getName(), merchantProfileBean));
		}
	    }
	} catch (Exception e) {
	    log.error(e, e);
	    ApplicationLogBean applicationLogBean = new ApplicationLogBean();
	    applicationLogBean.setType(ApplicationLogBean.TYPE_ERROR);
	    applicationLogBean.setClazz(clazz);
	    applicationLogBean.setMethod(method);
	    applicationLogBean.setMessage(e.getMessage());
	    applicationLogService.createApplicationLog(applicationLogBean);
	}
	return entryBeans;
    }

    @Override
    public List<EntryBean<String, Serializable>> deleteMerchantProfile(MerchantProfileBean merchantProfileBean) {
	String clazz = MerchantProfileService.class.getName();
	String method = "deleteMerchantProfile";
	List<EntryBean<String, Serializable>> entryBeans = null;
	MerchantProfile merchantProfile = null;
	try {
	    if (merchantProfileBean != null) {
		Date currentDate = DateUtils.getCurrentDate();
		String currentDateStr = StringUtils.formatDate(currentDate, StringUtils.PATTERN_DATETIME_PERSISTENCE);
		entryBeans = new ArrayList<EntryBean<String, Serializable>>();

		// validate
		List<Error> errors = formValidatorService.validate(clazz, method, merchantProfileBean);
		List<ErrorBean> errorBeans = new ArrayList<ErrorBean>();
		if (errors != null && !errors.isEmpty()) {
		    for (Error error : errors) {
			ErrorBean errorBean = new ErrorBean();
			BeanUtils.copyProperties(error, errorBean);
			errorBeans.add(errorBean);
		    }
		} else {
		    Long merchantProfileId = merchantProfileBean.getId();
		    merchantProfile = merchantProfilePersistenceService.findOne(merchantProfileId);
		    if (merchantProfile == null) {
			errorBeans.add(new ErrorBean(
				"errors.com.fw.service.bouser.MerchantProfileService.deleteMerchantProfile.notfoundMerchantProfile"));
		    }
		}
		// result
		if (errorBeans != null && !errorBeans.isEmpty()) {
		    entryBeans.add(new EntryBean<String, Serializable>(List.class.getName() + "." + ErrorBean.class.getName(),
			    (Serializable) errorBeans));
		} else {

		    // update status
		    merchantProfile.setMerchantStatus(MerchantProfile.STATUS_INACTIVE);
		    merchantProfile.setLastUpdateBy(merchantProfileBean.getLoginUsername());
		    merchantProfile.setLastUpdateDate(currentDateStr);
		    merchantProfile = merchantProfilePersistenceService.save(merchantProfile);

		    MerchantProfileBean resultBoUserBean = new MerchantProfileBean();
		    BeanUtils.copyProperties(merchantProfile, resultBoUserBean);
		    resultBoUserBean.setId(merchantProfile.getId());

		    // audit log
		    String logActionType = propertyService.getProperty("auditlog." + clazz + "." + method);
		    if (logActionType != null) {
			AuditLogBean auditLogBean = new AuditLogBean();
			auditLogBean.setLogActionType(logActionType);
			auditLogBean.setDescription("Merchant Profile, Merchant ID: " + merchantProfile.getMerchantId() + " deleted by "
				+ merchantProfileBean.getLoginUsername());
			auditLogBean.setGroupId(merchantProfileBean.getLoginRoleId());
			auditLogBean.setUserId(merchantProfileBean.getLoginUserId());
			auditLogBean.setDateTime(currentDateStr);
			auditLogBean.setUserIp(merchantProfileBean.getUserIp());
			auditLogService.createAuditLog(auditLogBean);
		    }
		    entryBeans.add(new EntryBean<String, Serializable>(resultBoUserBean.getClass().getName(), resultBoUserBean));
		}
	    }
	} catch (Exception e) {
	    log.error(e, e);
	    ApplicationLogBean applicationLogBean = new ApplicationLogBean();
	    applicationLogBean.setType(ApplicationLogBean.TYPE_ERROR);
	    applicationLogBean.setClazz(clazz);
	    applicationLogBean.setMethod(method);
	    applicationLogBean.setMessage(e.getMessage());
	    applicationLogService.createApplicationLog(applicationLogBean);
	}
	return entryBeans;
    }

    @Override
    public Boolean checkUniqueMerchantId(String merchantId) {
	Boolean result = Boolean.FALSE;
	try {
	    List<MerchantProfile> merchantProfiles = merchantProfilePersistenceService.selectByMerchantIdAndStatus(merchantId, null);
	    if (merchantProfiles == null || merchantProfiles.isEmpty()) {
		result = Boolean.TRUE;
	    }
	} catch (Exception e) {
	    log.error(e, e);
	}
	return result;
    }

    @Override
    public SearchResultBean<MerchantProfileBean> selectMerchantProfile(SearchCriteriaBean<SearchMerchantProfileBean> searchCriteriaBean) {
	SearchResultBean<MerchantProfileBean> searchResultBean = null;
	try {
	    if (searchCriteriaBean != null) {
		SearchMerchantProfileBean searchMerchantProfileBean = searchCriteriaBean.getCriteriaBean();
		if (searchMerchantProfileBean != null) {
		    final String merchantId = searchMerchantProfileBean.getMerchantId();
		    final String merchantCompanyName = searchMerchantProfileBean.getCompanyName();
		    final String merchantUrl = searchMerchantProfileBean.getMerchantUrl();
		    final Boolean hideMerchantTest = searchMerchantProfileBean.getHideMerchantTest();
		    final String projectContactPerson = searchMerchantProfileBean.getProjectContactPerson();
		    final String merchantServiceType = searchMerchantProfileBean.getMerchantServiceType();
		    final String merchantStatus = searchMerchantProfileBean.getStatus();
		    final List<Long> excludeMerchantIds = searchMerchantProfileBean.getExcludeMerchantIds();
		    final Boolean searchAllStatus = searchMerchantProfileBean.getSearchAllStatus();

		    Specification<MerchantProfile> specification = new Specification<MerchantProfile>() {
			@Override
			public Predicate toPredicate(Root<MerchantProfile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
			    List<Predicate> predicates = new ArrayList<Predicate>();
			    if (merchantId != null && !merchantId.isEmpty()) {
				predicates.add(cb.like(root.<String> get("merchantId"), "%" + merchantId + "%"));
			    }
			    if (merchantCompanyName != null && !merchantCompanyName.isEmpty()) {
				Predicate predicate1 = cb.like(root.<String> get("companyNameEn"), "%" + merchantCompanyName + "%");
				Predicate predicate2 = cb.like(root.<String> get("companyNameTh"), "%" + merchantCompanyName + "%");
				Predicate[] predicatesOr = new Predicate[] { predicate1, predicate2 };
				predicates.add(cb.or(predicatesOr));
			    }
			    if (merchantUrl != null && !merchantUrl.isEmpty()) {
				predicates.add(cb.like(root.<String> get("url"), "%" + merchantUrl + "%"));
			    }
			    if (hideMerchantTest != null && hideMerchantTest.booleanValue()) {
				predicates.add(cb.notEqual(root.<Boolean> get("isTestMerchant"), hideMerchantTest));
			    }
			    if (projectContactPerson != null && !projectContactPerson.isEmpty()) {
				Predicate predicate1 = cb.like(root.<String> get("contact1Name"), "%" + projectContactPerson + "%");
				Predicate predicate2 = cb.like(root.<String> get("contact2Name"), "%" + projectContactPerson + "%");
				Predicate predicate3 = cb.like(root.<String> get("contact3Name"), "%" + projectContactPerson + "%");
				Predicate predicate4 = cb.like(root.<String> get("contact4Name"), "%" + projectContactPerson + "%");

				Predicate[] predicatesOr = new Predicate[] { predicate1, predicate2, predicate3, predicate4 };
				predicates.add(cb.or(predicatesOr));
			    }
			    if (merchantServiceType != null && !merchantServiceType.isEmpty()) {
				predicates.add(cb.like(root.<String> get("merchantServiceType"), "%" + merchantServiceType + "%"));
			    }
			    if (merchantStatus != null && !merchantStatus.isEmpty()) {
				predicates.add(cb.equal(root.<String> get("merchantStatus"), merchantStatus));
			    } else {
				if (searchAllStatus == null || searchAllStatus.booleanValue() == false) {
				    predicates.add(cb.notEqual(root.<String> get("merchantStatus"), MerchantProfile.STATUS_CLOSED));
				}
			    }
			    if (excludeMerchantIds != null && !excludeMerchantIds.isEmpty()) {
				predicates.add(cb.not(root.<Long> get("id").in(excludeMerchantIds)));
			    }

			    Predicate result = cb.conjunction();
			    for (Predicate predicate : predicates) {
				result.getExpressions().add(predicate);
			    }
			    return result;
			}
		    };
		    Page<MerchantProfile> page = merchantProfilePersistenceService.findAll(specification,
			    PageRequestUtils.getPageRequest(searchCriteriaBean));
		    if (page != null) {
			DateFormat dateTimeFormat = new SimpleDateFormat(StringUtils.PATTERN_DATETIME_PERSISTENCE);
			searchResultBean = new SearchResultBean<MerchantProfileBean>();
			searchResultBean.setTotalElements(page.getTotalElements());
			searchResultBean.setTotalPages(page.getTotalPages());
			List<MerchantProfileBean> content = new ArrayList<MerchantProfileBean>();
			List<MerchantProfile> merchantProfiles = page.getContent();
			if (merchantProfiles != null && !merchantProfiles.isEmpty()) {
			    for (MerchantProfile merchantProfile : merchantProfiles) {
				MerchantProfileBean bean = new MerchantProfileBean();
				BeanUtils.copyProperties(merchantProfile, bean);
				bean.setId(merchantProfile.getId());

				if (merchantProfile.getCreateDate() != null && !merchantProfile.getCreateDate().isEmpty()) {
				    Date date = dateTimeFormat.parse(merchantProfile.getCreateDate());
				    bean.setCreateDate(date);
				}
				if (merchantProfile.getLastUpdateDate() != null && !merchantProfile.getLastUpdateDate().isEmpty()) {
				    Date date = dateTimeFormat.parse(merchantProfile.getLastUpdateDate());
				    bean.setLastUpdateDate(date);
				}

				content.add(bean);
			    }
			}
			searchResultBean.setContent(content);
		    }
		}
	    }
	} catch (Exception e) {
	    log.error(e, e);
	}
	return searchResultBean;
    }

    private boolean isDataChange(MerchantProfile merchantProfile, MerchantProfileBean merchantProfileBean) {
	boolean isChange = false;
	if (merchantProfile != null && merchantProfileBean != null) {
	    if (DataUtils.isChange(merchantProfile.getLogoId(), merchantProfileBean.getLogoId())
		    || DataUtils.isChange(merchantProfile.getIsTestMerchant(), merchantProfileBean.getIsTestMerchant())
		    || DataUtils.isChange(merchantProfile.getMerchantStatus(), merchantProfileBean.getMerchantStatus())
		    || DataUtils.isChange(merchantProfile.getMerchantNameEn(), merchantProfileBean.getMerchantNameEn())
		    || DataUtils.isChange(merchantProfile.getMerchantNameTh(), merchantProfileBean.getMerchantNameTh())
		    || DataUtils.isChange(merchantProfile.getCompanyNameEn(), merchantProfileBean.getCompanyNameEn())
		    || DataUtils.isChange(merchantProfile.getCompanyNameTh(), merchantProfileBean.getCompanyNameTh())
		    || DataUtils.isChange(merchantProfile.getBusinessRegNumber(), merchantProfileBean.getBusinessRegNumber())
		    || DataUtils.isChange(merchantProfile.getStatementName(), merchantProfileBean.getStatementName())
		    || DataUtils.isChange(merchantProfile.getCountryDomicile(), merchantProfileBean.getCountryDomicile())
		    || DataUtils.isChange(merchantProfile.getCountryRegion(), merchantProfileBean.getCountryRegion())
		    || DataUtils.isChange(merchantProfile.getBusinessAddress(), merchantProfileBean.getBusinessAddress())
		    || DataUtils.isChange(merchantProfile.getMailingAddress(), merchantProfileBean.getMailingAddress())
		    || DataUtils.isChange(merchantProfile.getUrl(), merchantProfileBean.getUrl())
		    || DataUtils.isChange(merchantProfile.getFaxNumber(), merchantProfileBean.getFaxNumber())
		    || DataUtils.isChange(merchantProfile.getTaxId(), merchantProfileBean.getTaxId())
		    || DataUtils.isChange(merchantProfile.getEnquiryNumber(), merchantProfileBean.getEnquiryNumber())
		    || DataUtils.isChange(merchantProfile.getContact1Name(), merchantProfileBean.getContact1Name())
		    || DataUtils.isChange(merchantProfile.getContact1Phone(), merchantProfileBean.getContact1Phone())
		    || DataUtils.isChange(merchantProfile.getContact1Mobile(), merchantProfileBean.getContact1Mobile())
		    || DataUtils.isChange(merchantProfile.getContact1Email(), merchantProfileBean.getContact1Email())
		    || DataUtils.isChange(merchantProfile.getContact2Name(), merchantProfileBean.getContact2Name())
		    || DataUtils.isChange(merchantProfile.getContact2Phone(), merchantProfileBean.getContact2Phone())
		    || DataUtils.isChange(merchantProfile.getContact2Mobile(), merchantProfileBean.getContact2Mobile())
		    || DataUtils.isChange(merchantProfile.getContact2Email(), merchantProfileBean.getContact2Email())
		    || DataUtils.isChange(merchantProfile.getContact3Name(), merchantProfileBean.getContact3Name())
		    || DataUtils.isChange(merchantProfile.getContact3Phone(), merchantProfileBean.getContact3Phone())
		    || DataUtils.isChange(merchantProfile.getContact3Mobile(), merchantProfileBean.getContact3Mobile())
		    || DataUtils.isChange(merchantProfile.getContact3Email(), merchantProfileBean.getContact3Email())
		    || DataUtils.isChange(merchantProfile.getContact4Name(), merchantProfileBean.getContact4Name())
		    || DataUtils.isChange(merchantProfile.getContact4Phone(), merchantProfileBean.getContact4Phone())
		    || DataUtils.isChange(merchantProfile.getContact4Mobile(), merchantProfileBean.getContact4Mobile())
		    || DataUtils.isChange(merchantProfile.getContact4Email(), merchantProfileBean.getContact4Email())) {
		isChange = true;
	    }
	}
	return isChange;
    }

    public byte[] exportMerchantProfileAsCSV(SearchCriteriaBean<SearchMerchantProfileBean> searchCriteriaBean) {
	try {
	    if (searchCriteriaBean != null) {
		SearchMerchantProfileBean searchMerchantProfileBean = searchCriteriaBean.getCriteriaBean();
		if (searchMerchantProfileBean != null) {
		    final String merchantId = searchMerchantProfileBean.getMerchantId();
		    final String merchantCompanyName = searchMerchantProfileBean.getCompanyName();
		    final String merchantUrl = searchMerchantProfileBean.getMerchantUrl();
		    final Boolean hideMerchantTest = searchMerchantProfileBean.getHideMerchantTest();
		    final String projectContactPerson = searchMerchantProfileBean.getProjectContactPerson();
		    final String merchantServiceType = searchMerchantProfileBean.getMerchantServiceType();
		    final String merchantStatus = searchMerchantProfileBean.getStatus();

		    Specification<MerchantProfile> specification = new Specification<MerchantProfile>() {
			@Override
			public Predicate toPredicate(Root<MerchantProfile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
			    List<Predicate> predicates = new ArrayList<Predicate>();
			    if (merchantId != null && !merchantId.isEmpty()) {
				predicates.add(cb.like(root.<String> get("merchantId"), "%" + merchantId + "%"));
			    }
			    if (merchantCompanyName != null && !merchantCompanyName.isEmpty()) {
				Predicate predicate1 = cb.like(root.<String> get("companyNameEn"), "%" + merchantCompanyName + "%");
				Predicate predicate2 = cb.like(root.<String> get("companyNameTh"), "%" + merchantCompanyName + "%");
				Predicate[] predicatesOr = new Predicate[] { predicate1, predicate2 };
				predicates.add(cb.or(predicatesOr));
			    }
			    if (merchantUrl != null && !merchantUrl.isEmpty()) {
				predicates.add(cb.like(root.<String> get("url"), "%" + merchantUrl + "%"));
			    }
			    if (hideMerchantTest != null && hideMerchantTest.booleanValue()) {
				predicates.add(cb.notEqual(root.<Boolean> get("isTestMerchant"), hideMerchantTest));
			    }
			    if (projectContactPerson != null && !projectContactPerson.isEmpty()) {
				Predicate predicate1 = cb.like(root.<String> get("contact1Name"), "%" + projectContactPerson + "%");
				Predicate predicate2 = cb.like(root.<String> get("contact2Name"), "%" + projectContactPerson + "%");
				Predicate predicate3 = cb.like(root.<String> get("contact3Name"), "%" + projectContactPerson + "%");
				Predicate predicate4 = cb.like(root.<String> get("contact4Name"), "%" + projectContactPerson + "%");

				Predicate[] predicatesOr = new Predicate[] { predicate1, predicate2, predicate3, predicate4 };
				predicates.add(cb.or(predicatesOr));
			    }
			    if (merchantServiceType != null && !merchantServiceType.isEmpty()) {
				predicates.add(cb.like(root.<String> get("merchantServiceType"), "%" + merchantServiceType + "%"));
			    }
			    if (merchantStatus != null && !merchantStatus.isEmpty()) {
				predicates.add(cb.equal(root.<String> get("merchantStatus"), merchantStatus));
			    } else {
				predicates.add(cb.notEqual(root.<String> get("merchantStatus"), MerchantProfile.STATUS_CLOSED));
			    }

			    Predicate result = cb.conjunction();
			    for (Predicate predicate : predicates) {
				result.getExpressions().add(predicate);
			    }
			    return result;
			}
		    };

		    searchCriteriaBean.setPage(1);
		    searchCriteriaBean.setSize(Integer.MAX_VALUE);

		    Page<MerchantProfile> page = merchantProfilePersistenceService.findAll(specification,
			    PageRequestUtils.getPageRequest(searchCriteriaBean));
		    if (page != null) {

			Map<String, String> statusMap = new HashMap<String, String>();
			Map<String, String> merchantServiceTypeMap = new HashMap<String, String>();

			List<EntryBean<String, String>> entryBeanServiceTypes = masterDataService.selectAllMerchantProfileServiceType();
			List<EntryBean<String, String>> entryBeanStatus = masterDataService.selectAllMerchantProfileStatus();

			if (entryBeanServiceTypes != null) {
			    for (EntryBean<String, String> entry : entryBeanServiceTypes) {
				merchantServiceTypeMap.put(entry.getKey(), entry.getValue());
			    }
			}
			if (entryBeanStatus != null) {
			    for (EntryBean<String, String> entry : entryBeanStatus) {
				statusMap.put(entry.getKey(), entry.getValue());
			    }
			}

			DateFormat dateTimeFormatPer = new SimpleDateFormat(StringUtils.PATTERN_DATETIME_PERSISTENCE);
			DateFormat dateTimeFormatUI = new SimpleDateFormat(StringUtils.PATTERN_DATETIME_UI);
			List<MerchantProfileCSVTemplate> content = new ArrayList<MerchantProfileCSVTemplate>();
			List<MerchantProfile> merchantProfiles = page.getContent();
			if (merchantProfiles != null && !merchantProfiles.isEmpty()) {
			    Long no = 0l;
			    for (MerchantProfile merchantProfile : merchantProfiles) {
				MerchantProfileCSVTemplate merchantProfileCSVTemplate = new MerchantProfileCSVTemplate();
				no++;
				merchantProfileCSVTemplate.setNo(no);
				merchantProfileCSVTemplate.setMerchantId(merchantProfile.getMerchantId());
				merchantProfileCSVTemplate.setMerchantName(merchantProfile.getMerchantNameEn());
				merchantProfileCSVTemplate.setCompanyName(merchantProfile.getCompanyNameEn());
				merchantProfileCSVTemplate.setMerchantUrl(merchantProfile.getUrl());
				merchantProfileCSVTemplate.setProjectContactPerson(merchantProfile.getContact1Name());
				merchantProfileCSVTemplate.setMerchantServiceType(merchantServiceTypeMap.get(merchantProfile
					.getMerchantServiceType()));
				merchantProfileCSVTemplate.setStatus(statusMap.get(merchantProfile.getMerchantStatus()));
				if (merchantProfile.getCreateDate() != null && !merchantProfile.getCreateDate().isEmpty()) {
				    Date date = dateTimeFormatPer.parse(merchantProfile.getCreateDate());
				    String dateStr = dateTimeFormatUI.format(date);
				    merchantProfileCSVTemplate.setCreateDateTime(dateStr);
				}
				if (merchantProfile.getLastUpdateDate() != null && !merchantProfile.getLastUpdateDate().isEmpty()) {
				    Date date = dateTimeFormatPer.parse(merchantProfile.getLastUpdateDate());
				    String dateStr = dateTimeFormatUI.format(date);
				    merchantProfileCSVTemplate.setLastUpdateDateTime(dateStr);
				}
				content.add(merchantProfileCSVTemplate);
			    }
			}

			if (!content.isEmpty()) {
			    String path = propertyService
				    .getProperty("com.fw.service.merchantprofile.MerchantProfileService.template.csv.path");
			    String encode = propertyService.getProperty("com.fw.service.merchantprofile.MerchantProfileService.encode.csv");
			    VelocityContext context = new VelocityContext();
			    String templatePath = this.getClass().getResource(path).getFile();
			    VelocityUtil vutil = new VelocityUtil(templatePath);

			    context.put(MerchantProfileCSVTemplate.TEMPLATE_ATTRIBUTE_MERCHANT_PROFILE_LIST, content);

			    String text = vutil.getReportAsString(context);
			    if (text != null) {
				return text.getBytes(encode);
			    }
			}
		    }
		}
	    }
	} catch (Exception e) {
	    log.error(e.getMessage(), e);
	}
	return null;
    }

    @Override
    public MerchantProfileBean getMerchantProfileByMerchantId(String merchantId) {
	MerchantProfileBean merchantProfileBean = null;
	try {
	    List<MerchantProfile> merchantProfiles = merchantProfilePersistenceService.selectByMerchantIdAndStatus(merchantId, null);
	    if (merchantProfiles != null && !merchantProfiles.isEmpty()) {
		MerchantProfile merchantProfile = merchantProfiles.get(0);
		if (merchantProfile != null) {
		    merchantProfileBean = new MerchantProfileBean();
		    BeanUtils.copyProperties(merchantProfile, merchantProfileBean);
		    merchantProfileBean.setId(merchantProfile.getId());
		}
	    }
	} catch (Exception e) {
	    log.error(e, e);
	}
	return merchantProfileBean;
    }

}
